/***
* ==++==
*
* Copyright (c) Microsoft Corporation.  All rights reserved.
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* procstore.h
*
* C++ Actors: actor state storage
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once

#include "actor_public.h"

namespace actors {
    
/// <summary>
/// The ProcessStorage class defines the abstract interface of any implementation of
/// actor checkpoint state.
/// </summary>
class ProcessStorage
{
public:
    /// <summary>
    /// Remove all storage associated with the actor represented by 'guid'
    /// </summary>
    virtual bool ClearProcess(const msg_guid &guid) = 0;

    /// <summary>
    /// Store the data passed in and associate it with 'guid' as the key. Also, note the type name of the
    /// actor class, so that it can be retrieved later and used for validation when restoring.
    /// </summary>
    virtual bool StoreProcess(const msg_guid &guid, const storage_block &data) = 0;

    /// <summary>
    /// Recover the checkpoint data associated with 'guid' (if any). Also retrieve the type name used by the type
    /// that created the checkpoint.
    /// </summary>
    virtual bool _recover(const msg_guid &guid, storage_block &data) = 0;
};

/// <summary>
/// Local file implementation of the actor storage interface
/// </summary>
class LocalFileStore : public ProcessStorage
{
public:
    _DISPIMP LocalFileStore(std::string baseFolder);

    /// <summary>
    /// Remove all storage associated with the actor represented by 'guid'
    /// </summary>
    bool ClearProcess(const msg_guid &guid);

    /// <summary>
    /// Store the data passed in and associate it with 'guid' as the key. Also, note the type name of the
    /// actor class, so that it can be retrieved later and used for validation when restoring.
    /// </summary>
    bool StoreProcess(const msg_guid &guid, const storage_block &data);
    /// <summary>
    /// Recover the checkpoint data associated with 'guid' (if any). Also retrieve the type name used by the type
    /// that created the checkpoint.
    /// </summary>
    bool _recover(const msg_guid &guid, storage_block &data);

private:
    std::string m_folder;
};

/// <summary>
/// Remote storage implementation, based on sample storage service. Remote storage may be made redundant at the
/// client, by keeping more than one service URI in the storage implementation.
/// </summary>
class RemoteStore : public ProcessStorage
{
public:
    RemoteStore(const std::string &uri) { AddStorageUri(uri); }
    RemoteStore(const std::vector<std::string> &uris)  { for (auto iter = uris.begin(); iter != uris.end(); iter++) AddStorageUri(*iter); }

    _DISPIMP ~RemoteStore();

    /// <summary>
    /// Add a storage service URI to the collection.
    /// </summary>
    _DISPIMP void AddStorageUri(const std::string &uri);

    /// <summary>
    /// Remove all storage associated with the actor represented by 'guid'
    /// </summary>
    _DISPIMP bool ClearProcess(const msg_guid &guid);

    /// <summary>
    /// Store the data passed in and associate it with 'guid' as the key. Also, note the type name of the
    /// actor class, so that it can be retrieved later and used for validation when restoring.
    /// </summary>
    _DISPIMP bool StoreProcess(const msg_guid &guid, const storage_block &data);

    /// <summary>
    /// Recover the checkpoint data associated with 'guid' (if any). Also retrieve the type name used by the type
    /// that created the checkpoint.
    /// </summary>
    _DISPIMP bool _recover(const msg_guid &guid, storage_block &data);

private:
    std::vector<PID> m_storage;
};

} // namespace actors